﻿
package extremefx.remoting {
	import flash.net.ObjectEncoding;
	import flash.net.registerClassAlias;
	import flash.utils.ByteArray;
	import flash.utils.describeType;
	
	/**
	 * @author Marcelo Volmaro
	 * Converts a plain vanilla object to be an instance of the class
	 * passed as the second variable.  This is not a recursive funtion
	 * and will only work for the first level of nesting.  When you have
	 * deeply nested objects, you first need to convert the nested
	 * objects to class instances, and then convert the top level object.
	 * 
	 * TODO: This method can be improved by making it recursive.  This would be 
	 * done by looking at the typeInfo returned from describeType and determining
	 * which properties represent custom classes.  Those classes would then
	 * be registerClassAlias'd using getDefinititonByName to get a reference,
	 * and then objectToInstance would be called on those properties to complete
	 * the recursive algorithm.
	 * 
	 * @param pObj The plain object that should be converted
	 * @param pClass The type to convert the object to
	 * @return a new instance of pClass populated with the values in pObj
	 */
	
	public function objectToInstance(pObj:Object, pClass:Class):* {
		var bytes:ByteArray = new ByteArray();
		bytes.objectEncoding = ObjectEncoding.AMF0;
		
		// Write out the bytes of the original object
		var objBytes:ByteArray = new ByteArray();
		objBytes.objectEncoding = ObjectEncoding.AMF0;
		objBytes.writeObject(pObj);
				
		// Register all of the classes so they can be decoded via AMF
		var typeInfo:XML = describeType(pClass);
		var fullyQualifiedName:String = typeInfo.@name.toString().replace( /::/, "." );
		registerClassAlias(fullyQualifiedName, pClass);
		
		var len:int = fullyQualifiedName.length;
		bytes.writeByte(0x10);  // 0x10 is AMF0 for "typed object (class instance)"
		bytes.writeUTF(fullyQualifiedName);
		bytes.writeBytes(objBytes, 1);

		bytes.position = 0;
		return bytes.readObject();
	}
}
